#ifndef _SOMB_MANAGER_H_
#define _SOMB_MANAGER_H_

#include "pthread.h"

#include "somb_common.h"
#include "uthash.h"
#include "somb_daemon.pb.h"

typedef enum
{
    SOMB_SUBNS_STATUS_INVALID,
    SOMB_SUBNS_STATUS_ONLINE,
    SOMB_SUBNS_STATUS_OFFLINE,
}E_SOMB_SUBNS_STATUS;

typedef struct
{
    char addr[SOMB_ADDR_LEN];
    int skfd;
    uint32_t ref;
}ST_SERVICE_ADDR;


struct somb_local_sub_ns{
    int localpid;
    char localexename[32]; // it means sub_ns_name
    uint32_t sub_ns_id;
    int sk;//local subns will conect(daemon) with this sk
    char sub_ns_addr[SOMB_ADDR_LEN]; //for daemon and ctrl
    int sk1;//local sub ns will listen to this sk1
    char sub_ns_addr1[SOMB_ADDR_LEN];//for other sub ns
    int ctrl_sk;
    pthread_mutex_t SubNsListLock;
    pthread_mutex_t sk_lock;
    pthread_cond_t sk_cond;
    uint32_t cond_MsgId;
    void *cond_MsgData;
};


struct somb_mngr_sub_ns_resp_data {
    uint32_t ServiceId;
    uint8_t MsgType;
    uint8_t MsgSeqId;
    uint32_t sub_ns_id;
    uint32_t data_len;
    bool bComplete;
    void *data;
    struct somb_mngr_sub_ns_resp_data *prev;
    struct somb_mngr_sub_ns_resp_data *next;
};

/*
struct somb_mngr_service_item;
struct somb_mngr_subns_service_list
{
    struct somb_mngr_service_item *service_item;
    struct somb_mngr_subns_service_list *prev;
    struct somb_mngr_subns_service_list *next;
};
*/

struct somb_mngr_sub_ns{
    int skfd;//client connect the current remote peer sub ns 
    int skfd2;//server accept the current remote peer connection
    E_SOMB_SUBNS_STATUS SubNsStatus;
    uint32_t sub_ns_id;
    char sub_ns_addr[SOMB_ADDR_LEN]; /*addr for communicate with other sub ns*/
    char sub_ns_name[32];
    int8_t MsgSeqId;
    //struct somb_mngr_subns_service_list *owned_service_head;
    struct somb_mngr_sub_ns_resp_data *resp_data_head;
    pthread_mutex_t mutex_lock;
    pthread_cond_t cond;
    void *private_data; /*private data*/
    //struct somb_mngr_sub_ns *next; /*make this struture as a list */
    //struct somb_mngr_sub_ns *next; /*make this struture as a list */
    UT_hash_handle hh;         /* makes this structure hashable */
};

struct somb_mngr_service_subns_item
{
    struct somb_mngr_sub_ns *pstSubNs;
    struct somb_mngr_service_subns_item *prev;
    struct somb_mngr_service_subns_item *next;
};

typedef struct somb_mngr_service_item{
    uint32_t ServiceId;                    /* key */
    uint8_t  ServiceType; /*Method or Event*/

    /*when the service is provided by local , the ServiceCount count the number of being requested(method) or be triggered(event). 
     * otherwise, the ServiceCount count the number of requesting(method) or listen callback being called(event)*/
    uint32_t  ServiceCount; 

    /*when the service is provided by local , 
     * the ServiceFailCount count the number of being requested(method) complete fail or triggered(event) fail,. 
     * otherwise, the ServiceFailCount count the number of requesting(method) send fail or listen callback being called(event) fail(no callback)*/
    uint32_t  ServiceFailCount; 

    E_SOMB_SERVICEID_STATUS status;
    void * ServicePriv;
    void * AsyncCB;
    struct somb_mngr_sub_ns *pstSubNs; /* the SerivceId is provided by pstSubNs */
    struct somb_mngr_service_subns_item *listen_subns_listhead;
    UT_hash_handle hh;         /* makes this structure hashable */
}ST_SOMB_LIB_SERVICE_LIST;

struct somb_mngr_reg_serviceitem
{
    uint32_t ServiceId;
    uint8_t ServiceType;
    uint32_t ServiceFlags;
};

extern ST_SOMB_LIB_SERVICE_LIST* pstSOMBManagerCheckServiceInfo(uint32_t ServiceId);
extern ST_SOMB_LIB_SERVICE_LIST * pstSOMBManagerGetServiceInfo(uint32_t ServiceId);
extern ST_SOMB_LIB_SERVICE_LIST* pstSOMBManagerPureGetServiceInfo(uint32_t ServiceId);
struct somb_mngr_sub_ns *pstSOMB_GetSubNsById(uint32_t sub_ns_id);
//struct somb_mngr_sub_ns *pstSOMB_GetSubNsByAddr(uint8_t SubNsAddr[]);
struct somb_mngr_sub_ns *pstSOMB_GetSubNsBySkfd2(uint32_t skfd2);
struct somb_mngr_sub_ns *pstSOMB_Manager_Find_SubNs(uint32_t sub_ns_id);
extern struct somb_local_sub_ns *pstSOMB_GetLocalSubNs(void);
extern int32_t somb_manager_connect_remote_subns(struct somb_mngr_sub_ns *pstSubNs);
extern struct somb_mngr_sub_ns *pstSOMB_Manager_SaveSubNs(uint32_t sub_ns_id,char *sub_ns_addr,char* sub_ns_name);
extern int32_t i32SOMB_Manager_SubNs_Init(uint32_t *pSubNsId);
//extern struct somb_mngr_service_item *pstSOMB_Manager_SaveService(uint32_t ServiceId,uint8_t ServiceType,void *Priv,uint32_t sub_ns_id,char sub_ns_addr[],char sub_ns_name[]);
extern struct somb_mngr_service_item *pstSOMB_Manager_SaveService(uint32_t ServiceId,uint8_t ServiceType,void *Priv,struct somb_mngr_sub_ns *pstSubNs);
extern int32_t i32SOMB_Manager_Connect_Daemon(void);
extern int32_t i32SOMB_Manager_RegisterService_Daemon(struct somb_mngr_reg_serviceitem pui32ServiceList[],uint32_t Size);
extern int32_t i32SOMB_Manager_RegisterListenEvent_2_Daemon(struct somb_mngr_reg_serviceitem pui32ServiceList[],uint32_t ServiceSize,bool reg);
extern int32_t i32SOMB_Manager_ChangeServiceStatus_2_Daemon(somb_msg_set_service_available *ServiceAvailableMsg);
extern int32_t i32SOMB_Manager_ChangeServiceStatusWithMask_2_Daemon(somb_msg_set_service_available_with_mask *MaskAvailabeMsg);
    

extern void vSOMB_Manager_Save_Method_AsyncCB(uint32_t ServiceId, PF_SOMB_METHOD_ASYNC_CB pfMthAsyncFunc);
extern PF_SOMB_METHOD_ASYNC_CB pfSOMB_Manager_Get_Method_AsyncCB(uint32_t ServiceId);

extern void vSOMB_Manager_Resp_Process(uint32_t Msgid,const pb_msgdesc_t * fields,uint32_t MsgSize,uint8_t *buffer,uint32_t buffer_len);
extern void vSOMB_Manager_Recv_Listen_SubNs_Process(uint8_t *buffer,uint32_t buffer_len);
extern void vSOMB_Manager_Report_Service_OnAvailable(uint8_t *buffer,uint32_t buffer_len);
extern void vsomb_manager_get_service_statistic(somb_subns_work_status *statistic) ;
#endif //_SOMB_MANAGER_H_
